package config

import (
	"strings"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

// IsSet 判断指定配置Key是否存在, Key不区分大小写
func IsSet(key string) bool {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().IsSet(key)
}

// InConfig 判断指定配置Key是否存在(包含别名), Key不区分大小写
func InConfig(key string) bool {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().InConfig(key)
}

// Get 获取指定配置Key的配置项, Key不区分大小写
//   - 返回值: 配置项(不存在返回nil)
func Get(key string) (val any) {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().Get(key)
}

// GetExist 获取指定配置Key的配置项, Key不区分大小写
//   - 返回值: 配置项(不存在返回nil), 配置项是否存在(Bool)
func GetExist(key string) (val any, exists bool) {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	if deafult().IsSet(key) {
		return deafult().Get(key), true
	}
	return nil, false
}

// GetViper 获取全局默认的Viper实例
func GetViper() *viper.Viper {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult()
}

// Set 覆盖指定配置Key的配置项, Key不区分大小写
func Set(key string, value any) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().Set(key, value)
}

// SetDefault 设置指定配置Key的默认值, Key不区分大小写
func SetDefault(key string, value any) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().SetDefault(key, value)
}

// RegisterAlias 创建指定配置key的别名，用于同一个配置项基于别名的另一个访问键
func RegisterAlias(alias, key string) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().RegisterAlias(alias, key)
}

// WriteConfigAs writes current configuration to a given filename.
func WriteConfigAs(filename string) error {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	return deafult().WriteConfigAs(filename)
}

// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
// E.g. if your prefix is "spf", the env registry will look for env
// variables that start with "SPF_".
func SetEnvPrefix(in string) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().SetEnvPrefix(in)
}
func GetEnvPrefix() string {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().GetEnvPrefix()
}

// SetEnvKeyReplacer sets the strings.Replacer on the viper object
// Useful for mapping an environmental variable to a key that does
// not match it.
func SetEnvKeyReplacer(r *strings.Replacer) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().SetEnvKeyReplacer(r)
}

// AutomaticEnv makes Viper check if environment variables match any of the existing keys
// (config, default or flags). If matching env vars are found, they are loaded into Viper.
func AutomaticEnv() {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().AutomaticEnv()
}

// AllowEmptyEnv tells Viper to consider set,
// but empty environment variables as valid values instead of falling back.
// For backward compatibility reasons this is false by default.
func AllowEmptyEnv(allowEmptyEnv bool) {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	deafult().AllowEmptyEnv(allowEmptyEnv)
}

// BindEnv binds a Viper key to a ENV variable.
// ENV variables are case sensitive.
// If only a key is provided, it will use the env key matching the key, uppercased.
// If more arguments are provided, they will represent the env variable names that
// should bind to this key and will be taken in the specified order.
// EnvPrefix will be used when set when env name is not provided.
func BindEnv(input ...string) error {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	return deafult().BindEnv(input...)
}

// BindPFlag binds a specific key to a pflag (as used by cobra).
// Example (where serverCmd is a Cobra instance):
// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
// BindPFlag("port", serverCmd.Flags().Lookup("port"))
func BindPFlag(key string, flag *pflag.Flag) error {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	return deafult().BindPFlag(key, flag)
}

// BindPFlags binds a full flag set to the configuration, using each flag's long
// name as the config key.
func BindPFlags(flags *pflag.FlagSet) error {
	defaultMu.Lock()
	defer defaultMu.Unlock()
	return deafult().BindPFlags(flags)
}

// AllKeys 获取所有配置Key
func AllKeys() []string {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().AllKeys()
}

// AllSettings 获取所有配置项
func AllSettings() map[string]any {
	defaultMu.RLock()
	defer defaultMu.RUnlock()
	return deafult().AllSettings()
}
